
--[[
	**********************
	* SvFrame - thomasfn *
	**********************
	SvProtect.lua - A plugin that adds area protection
]]

dofile( "lua/SvFrame/plugin_header.lua" )

PLUGIN.Name = "areaprotect"
PLUGIN.Title = "SvProtect"
PLUGIN.Author = "thomasfn"
PLUGIN.Folder = "SvProtect"

local areaData = {}

function PLUGIN:Init()
	svr.AddFlag( "areaprotect" )
	
	self:Command( "protect", self.Protect, function( ply )
		if (svr.PlayerHasFlag( ply, FLAG_AREAPROTECT )) then return true end
		ply:ChatPrint( COL_RED, "You do not have the ", COL_TEAL, "areaprotect", COL_RED, " flag!" )
		return false
	end )
	
	self:Hook( "player.breakblock", self.BreakBlock )
	self:Hook( "player.placeblock", self.PlaceBlock )
	--self:Hook( "player.placesign", self.PlaceSign )
	
	self:Hook( "player.digblock", self.LeftClick )
	self:Hook( "block.activate", self.RightClick )
	
	self:LoadAreaData()
	
end

--svr.TestHook( "player.digblock" )
--svr.TestHook( "block.activate" )

function PLUGIN:LoadAreaData()
	svr.Print( "Loading area data for SvProtect..." )
	local b, res = svr.FileToTable( "SvProtect/data/area" )
	if (not b) then return svr.Print( "Failed to load area data (" .. res .. ")" ) end
	areaData = res
end

function PLUGIN:SaveAreaData()
	local b, res = svr.TableToFile( "SvProtect/data/area", areaData )
	if (not b) then return svr.Print( "Failed to load save data (" .. res .. ")" ) end
end

function PLUGIN:FindArea( x, z )
	for i=1, #areaData do
		local area = areaData[i]
		if ((x >= area.x1) and (x <= area.x2) and (z >= area.z1) and (z <= area.z2)) then return area end
	end
end

function PLUGIN:PlayerAccess( ply, x, z, verb )
	if (svr.PlayerHasFlag( ply, "areaprotect" )) then return end
	local area = self:FindArea( x, z )
	if (not area) then return end
	for i=1, #area.Access do
		if (ply.Username:lower() == area.Access[i]:lower()) then return end
	end
	ply:ChatPrint( COL_RED, "This area is protected, you can't " .. verb .. " here!" )
	return false
end

function PLUGIN:BreakBlock( ply, block, face )
	return self:PlayerAccess( ply,block.X, block.Z, "dig" )
end

function PLUGIN:PlaceBlock( ply, block, face )
	return self:PlayerAccess( ply, block.X, block.Z, "build" )
end

function PLUGIN:LeftClick( ply, block, face )
	--print( "Left click! " .. tostring( ply ) .. "," .. tostring( block ) .. "," .. tostring( face ) )
	if (not svr.PlayerHasFlag( ply, "areaprotect" )) then return self:PlayerAccess( ply, block.X, block.Z, "dig" ) end
	local item = ply.GetHeldItem()
	if (not item) then return end
	if (not item or item.Id ~= 280) then return end
	ply.SelPtA = { x = block.X, z = block.Z }
	ply:ChatPrint( COL_GREEN, "[SvProtect] ", COL_WHITE, "First point selected." )
end

function PLUGIN:RightClick( ply, block )
	--print( "Right click! " .. tostring( ply ) .. "," .. tostring( block ) .. "," .. tostring( face ) )
	if (not svr.PlayerHasFlag( ply, "areaprotect" )) then return end
	local item = ply.GetHeldItem()
	if (not item) then return end
	if (not item or item.Id ~= 280) then return end
	ply.SelPtB = { x = block.X, z = block.Z }
	ply:ChatPrint( COL_GREEN, "[SvProtect] ", COL_WHITE, "Second point selected." )
end

local function Intersect( a, b )
	return not ((a.x1 < b.x2) or (a.x2 < b.x1) or (a.z1 > b.z2) or (a.z2 < b.z1))
end

PLUGIN.Protect = {
	remove = function( ply, args )
		local area = svr.GetPlugin( "areaprotect" ):FindArea( ply.Position.X, ply.Position.Z )
		if (not area) then
			ply:ChatPrint( COL_RED, "You are not currently in a protected area!" )
			return
		end
		table.removevalue( areaData, area )
		svr.GetPlugin( "areaprotect" ):SaveAreaData()
		ply:ChatPrint( COL_GREEN, "The ", COL_WHITE, (area.x2 - area.x1) .. "x" .. (area.z2 - area.z1), COL_GREEN, " area you were stood in has been removed." )
	end,
	add = function( ply, args )
		if (not ply.SelPtA) then return ply:ChatPrint( COL_RED, "You need to select the first point!" ) end
		if (not ply.SelPtB) then return ply:ChatPrint( COL_RED, "You need to select the second point!" ) end
		local newarea = {
			x1 = math.min( ply.SelPtA.x, ply.SelPtB.x ),
			x2 = math.max( ply.SelPtA.x, ply.SelPtB.x ),
			z1 = math.min( ply.SelPtA.z, ply.SelPtB.z ),
			z2 = math.max( ply.SelPtA.z, ply.SelPtB.z )
		}
		for i=1, #areaData do
			if (Intersect( areaData[i], newarea )) then
				ply:ChatPrint( COL_RED, "The selected area overlaps another protected area!" )
				return
			end
		end
		newarea.Access = { "_fake_" }
		table.insert( areaData, newarea )
		svr.GetPlugin( "areaprotect" ):SaveAreaData()
		ply:ChatPrint( COL_GREEN, "The ", COL_WHITE, (newarea.x2 - newarea.x1) .. "x" .. (newarea.z2 - newarea.z1), COL_GREEN, " area you selected has been protected." )
	end,
	["+"] = function( ply, args )
		if (not svr.CheckArg( args, 1, "string" )) then return ply:ChatPrint( COL_WHITE, "Syntax: /protect + <name>" ) end
		local area = svr.GetPlugin( "areaprotect" ):FindArea( ply.Position.X, ply.Position.Z )
		if (not area) then
			ply:ChatPrint( COL_RED, "You are not currently in a protected area!" )
			return
		end
		for _, v in pairs( area.Access ) do
			if (v:lower() == args[1]:lower()) then
				ply:ChatPrint( COL_RED, "That player is already on the access list of this area!" )
				return
			end
		end
		table.insert( area.Access, args[1] )
		svr.GetPlugin( "areaprotect" ):SaveAreaData()
		ply:ChatPrint( COL_GREEN, "Player '", COL_WHITE, args[1], COL_GREEN, "' was granted access to this area." )
	end,
	["-"] = function( ply, args )
		if (not svr.CheckArg( args, 1, "string" )) then return ply:ChatPrint( COL_WHITE, "Syntax: /protect - <name>" ) end
		if (args[1] == "_fake_") then return end
		local area = svr.GetPlugin( "areaprotect" ):FindArea( ply.Position.X, ply.Position.Z )
		if (not area) then
			ply:ChatPrint( COL_RED, "You are not currently in a protected area!" )
			return
		end
		local found = false
		for k, v in pairs( area.Access ) do
			if (v:lower() == args[1]:lower()) then
				table.remove( area.Access, k )
				found = true
				break
			end
		end
		if (not found) then
			ply:ChatPrint( COL_RED, "That player is not on the access list of this area!" )
			return
		end
		svr.GetPlugin( "areaprotect" ):SaveAreaData()
		ply:ChatPrint( COL_GREEN, "The access of player '", COL_WHITE, args[1], COL_GREEN, "' was revoked from this area." )
	end,
	access = function( ply, args )
		local area = svr.GetPlugin( "areaprotect" ):FindArea( ply.Position.X, ply.Position.Z )
		if (not area) then
			ply:ChatPrint( COL_RED, "You are not currently in a protected area!" )
			return
		end
		ply:ChatPrint( COL_WHITE, "Players with access to this area:" )
		local tmp = {}
		for _, name in pairs( area.Access ) do
			if (name ~= "_fake_") then tmp[ #tmp + 1 ] = name end
		end
		ply:ChatPrint( COL_WHITE, table.concat( tmp ) )
	end
}

PLUGIN:FinishLoad()